package cn.ywyself.extend.render;

import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import com.wf.captcha.*;

import javax.servlet.http.Cookie;
import java.util.Random;

/**
 * 验证码
 *
 * @Author: ywyself
 * @Created: 2018-10-09 9:16
 */
public class YsCaptchaRender extends Render {

    private static final Random random = new Random();

    private static final String CAPTCHA_PREFIX = "_YsCaptcha_";

    private static final int CAPTCHA_AGE = 60 * 3;

    /**
     * 普通验证码
     */
    public static final int DEFAULT = 0;

    /**
     * GIF
     */
    public static final int DEFAULT_GIF = 1;

    /**
     * 中文
     */
    public static final int CHINESE = 2;

    /**
     * 中文GIF
     */
    public static final int CHINESE_GIF = 3;

    private Captcha captcha;

    private String scenes;

    /**
     * @param scenes 使用场景
     */
    public YsCaptchaRender(String scenes) {
        this(scenes, random.nextInt(100) % 4);
    }

    /**
     * @param scenes 使用场景
     * @param type   类型
     */
    public YsCaptchaRender(String scenes, int type) {
        if (StrKit.isBlank(scenes)) {
            return;
        }
        this.scenes = scenes;
        setCaptcha(type);
    }

    private void setCaptcha(int type) {
        switch (type) {
            case CHINESE:
                // 中文验证码
                this.captcha = new ChineseCaptcha(120, 40, 4);
                break;
            case CHINESE_GIF:
                // 中文GIF验证码
                this.captcha = new ChineseGifCaptcha(120, 40, 3);
                break;
            case DEFAULT_GIF:
                // GIF验证码
                this.captcha = new GifCaptcha(120, 40, 4);
                break;
            default:
                this.captcha = new SpecCaptcha(120, 40, 5);
        }
    }

    /**
     * Render to client
     */
    @Override
    public void render() {
        if (this.captcha == null) {
            return;
        }
        String text = new String(this.captcha.textChar());
        // 添加cookie
        Cookie cookie = new Cookie(CAPTCHA_PREFIX + this.scenes, "yzm");
        cookie.setMaxAge(CAPTCHA_AGE);
        cookie.setPath("/");
        response.addCookie(cookie);
        // 添加session
        request.getSession(true).setAttribute(CAPTCHA_PREFIX + this.scenes, text);
        // 储存在redis中

        // 渲染
        try {
            this.captcha.out(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RenderException();
        }
    }

    /**
     * 验证
     *
     * @param controller this 控制器
     * @param text       输入的验证码
     * @param scenes     验证码使用场景
     * @return true|验证通过
     */
    public static boolean verify(Controller controller, String text, String scenes) {
        // 检查输入值
        if (StrKit.isBlank(text)) {
            return false;
        }
        // 检查场景是否一致
        if (StrKit.isBlank(scenes)) {
            return false;
        }
        // 具体场景验证码的key
        String key = CAPTCHA_PREFIX + scenes;
        // 依据具体场景 读取cookie value
        String cookieVal = controller.getCookie(key);
        if (!"yzm".equals(cookieVal)) {
            return false;
        }
        // 获取session中的验证码文本，集群应该使用redis
        String sessionVal = controller.getSessionAttr(key);
        if (StrKit.isBlank(sessionVal)) {
            return false;
        }
        if (text.equalsIgnoreCase(sessionVal)) {
            // 移除session
            controller.removeSessionAttr(key);
            // 移除cookie
            controller.removeCookie(key);
            return true;
        } else {
            return false;
        }
    }
}
